<template>
  <div class="zlst-frame-nav">
    <div :id="treeId + key" v-for="(item,key) in navData" :key="key" class="ztree"></div>
  </div>
</template>

<script>
  // 引入ztree 的解决办法
  import "../../../static/ztree/css/zTreeStyle/zTreeStyle.css"
  import "../../../static/ztree/js/jquery.ztree.all.js"
  import Vue from "vue"

  // 导航的唯一标志
  var treeId = "nav" + new Date().getTime() + "" + Math.floor(Math.random() * 10000);

  function addDiyDom(treeId, treeNode) {
      var spaceWidth = 5;
      // 节点前面的展开 收缩 图标对象
      var switchObj = $("#" + treeNode.tId + "_switch");
      // 节点图标
      var icoObj = $("#" + treeNode.tId + "_ico");
      var spanObj = $("#" + treeNode.tId + "_span");
      // 删除a 标签的href属性，防止产生一个新的窗口
      $("#" + treeNode.tId+ "_a").removeAttr("href");
      // 判断是否显示菜单图标
      if(treeNode.iconName != undefined){
          spanObj.html('<i class="icon iconfont '+treeNode.iconName+'" style="font-size: 14px;margin-right: 5px;"></i>'+spanObj.html());
      }
      // 删除默认的收缩 和 展开 图标
      switchObj.remove();
      // 将默认的收缩 和 展开 图标对象 放在 节点图标对象前面
      icoObj.before(switchObj);
      if (treeNode.level > 0) {
          var spaceStr = "<span style='display: inline-block;width:" + (spaceWidth * treeNode.level) + "px'></span>";
          switchObj.before(spaceStr);
      }
      // 节点下面的a 标签对象
      var aObj = $("#" + treeNode.tId + "_a");
  }

  /**
   * ztree 初始化完成的事情
   */
  function navTreeTools(vueObj){
    this.init(vueObj);
  }
  navTreeTools.prototype = {
    init : function (vueObj) {
      // 用来缓存ztree对象，直接操作ztree树的
      this.ztreeObj = null;
      // zlst 的Ztree对象，这个是提供给用户使用的
      this.zlstZtreeObj = null;
      // 数据结构是simpleData 并且 显示的字段与默认字段不一致
      if(vueObj.isSimpleData == true && vueObj.nodeHtmlKey != "nodeHtml"){
        // 重置数据
        this.ztreeDataFormat(vueObj);
      }
      // 获取默认 ztreeSetting 配置信息
      var setting = this.getInstanceSetting(vueObj);
      // 获取用户的配置信息
      var userSetting = this.resetSetting(setting, vueObj);
      // 初始化ztree对象
      this.createZtree(userSetting,vueObj);
    },
    /**
     * 创建ztree对象，最终完成初始化的动作，并且发出初始化完成的事件
     */
    createZtree : function (ztreeSetting, vueObj) {

      // 数据结构是simpleData 并且 显示的字段与默认字段不一致
      if(vueObj.isSimpleData != true){
        // 重置数据
        ztreeSetting.data.simpleData = {};
      }
      // 缓存 ztreeStting 的配置信息
      vueObj.setZtreeSetting(ztreeSetting);
      // 创建ztree
      var length = vueObj.navData.length;
      for(var i = 0; i < length; i++){
        var settingData = vueObj.navData[i];
        $.fn.zTree.init($(this.getTreeId()+""+i), ztreeSetting, settingData);
      }
      // 获取zTreeObj 对象
      this.ztreeObj = $.fn.zTree.getZTreeObj(this.getTreeIdStr());
      // zlst 的Ztree对象，这个是提供给用户使用的
      this.zlstZtreeObj = this.zlstVueZtreeObj(this.ztreeObj);
      // 初始化完成触发的事件
      vueObj.$emit("ztree-inited", {
        "zlstZtreeObj": this.zlstZtreeObj,
        "zTreeObj": this.ztreeObj
      });
    },
    /**
     * 根据用户传递的参数，重置ztree的配置，然后返回
     **/
    resetSetting : function (setting,vueObj) {
      // 设置node 节点的ID 和 PID 的标识
      setting.data.simpleData.idKey = vueObj.nodeIdKey;
      setting.data.simpleData.pIdKey = vueObj.nodePidKey;
      // 是否是simpleData 格式的数据（即数组的形式，非JSON格式）
      setting.data.simpleData.enable = vueObj.isSimpleData;

      // 如果是outlook 风格，需要添加自定义渲染节点的方法
      if(vueObj.isOutlookStyle){
        setting.view["addDiyDom"] = addDiyDom;
        setting.check["enable"] = false;
      }

      return setting;
    },

    /**
     * zTree 的参数配置，深入使用请参考 API 文档（setting 配置详解）
     * @param vueObj 代表当前vue 对象
     */
    getInstanceSetting : function (vueObj){
      // that 代表ztreeVueTools对象
      var that = this;
      var resutlSetting = {
        data: {
          simpleData: {
            // 是否是以简单的数据格式作为数据（非JSON，没有直观的显示层级）
            enable: true,
            idKey: "id",
            pIdKey: "pid",
          },
        },
        view:{
//        // 是否显示树的连线
//        showLine: false,
//        // 是否显示图标icon
//        showIcon:false,
//        // 设置是否允许同时选中多个节点
//        selectedMulti: false,
//        //点击展开按钮
//        dblClickExpand: false,
//        //      dblClickExpand: false,
//        //是否outlook风格
          addDiyDom: addDiyDom,
          showLine: false,
          showIcon: false,
          selectedMulti: false,
          dblClickExpand: false,
        },
        check:{
          // 是否允许多选
          enable: false,
        },
          // 是否允许编辑，如果允许编辑，则可以添加、重命名、删除节点的功能，默认是不允许删除
        edit:{
          enable: false,
          drag:{
            // 是否允许拖拽
            isMove: true,
            prev: true,
            inner: true,
            next: true,
          },
          // 是否显示移动节点按钮
          showRemoveBtn: true,
          // 是否显示重命名节点按钮
          showRenameBtn: true,
        },
        callback: {
          // 点击鼠标右键
          onRightClick: function(){
            // 第一个参数是  jquery.event事件对象，第二个参数是 nodeObject 节点对象，第三个参数是 jquery.ztree对象
            vueObj.$emit("on-right-click",arguments[0],arguments[2],that.ztreeObj);
          },
          // 点击事件
          onClick: function(){
            // 第一个参数是  jquery.event事件对象，第二个参数是 nodeObject 节点对象，第三个参数是 jquery.ztree对象
//                        vueObj.$emit("on-click",arguments[0],arguments[2],that.ztreeObj);
            var nodeObject = arguments[2];
            if(nodeObject.path != undefined){
              vueObj.$emit("link", nodeObject.url, nodeObject.name);
            }
          },
          // 折叠事件
          onCollapse: function(){
            // 第一个参数是  jquery.event事件对象，第二个参数是 nodeObject 节点对象，第三个参数是 jquery.ztree对象
            vueObj.$emit("on-collapse",arguments[0],arguments[2],that.ztreeObj);
          },
          // 展开事件
          onExpand: function(){
            // 第一个参数是  jquery.event事件对象，第二个参数是 nodeObject 节点对象，第三个参数是 jquery.ztree对象
            vueObj.$emit("on-expand",arguments[0],arguments[2],that.ztreeObj);
          },
          // 多选 选中事件
          onCheck: function(){
            // 第一个参数是  jquery.event事件对象，第二个参数是 nodeObject 节点对象，第三个参数是 jquery.ztree对象
            vueObj.$emit("on-check",arguments[0],arguments[2],that.ztreeObj);
          },
          // 拖拽释放时 触发的事件
          onDrop: function(){
            // 第一个参数是  jquery.event事件对象，第二个参数是 nodeObject 节点对象，第三个参数是 jquery.ztree对象
            vueObj.$emit("on-drop",arguments[0],arguments[2],that.ztreeObj);
          },
          // 重命名 触发的事件
          onRename: function(){
            // 第一个参数是  jquery.event事件对象，第二个参数是 nodeObject 节点对象，第三个参数是 jquery.ztree对象
            vueObj.$emit("on-rename",arguments[0],arguments[2],that.ztreeObj);
          },
          // 删除节点 触发的事件
          onRemove: function(){
            // 第一个参数是  jquery.event事件对象，第二个参数是 nodeObject 节点对象，第三个参数是 jquery.ztree对象
            vueObj.$emit("on-remove",arguments[0],arguments[2],that.ztreeObj);
          },
          // 创建节点触发 触发的事件
          onNodeCreated: function(){
            // 第一个参数是  jquery.event事件对象，第二个参数是 nodeObject 节点对象，第三个参数是 jquery.ztree对象
            vueObj.$emit("on-node-created",arguments[0],arguments[2],that.ztreeObj);
          },
        }
      };
      return resutlSetting;
    },

    /**
     * 传递一个ztree Obj 对象
     */
    zlstVueZtreeObj : function (zTreeObj){
      // 缓存原始的ztree对象
      var currentZtreeObj = zTreeObj;

      /**
       * 展开所有节点
       */
      var expandAll = function (){
        currentZtreeObj.expandAll(true);
      };

      /**
       * 展开指定的节点，子节点不递归展开
       * @param treeNode 指定展开的节点对象
       */
      var expandNodeOnly = function (treeNode) {
        return currentZtreeObj.expandNode(treeNode, true, false, true);
      };
      /**
       * 展开指定的节点，子节点递归展开
       * @param treeNode 指定展开的节点对象
       */
      var expandNodeAll = function (treeNode) {
        return currentZtreeObj.expandNode(treeNode, true, true, true);
      };

      /**
       * 折叠所有节点
       */
      var collapseAll = function () {
        currentZtreeObj.expandAll(false);
      };

      /**
       * 展开指定的节点，子节点不递归展开
       * @param treeNode 指定展开的节点对象
       */
      var collapseNodeOnly = function (treeNode) {
        return currentZtreeObj.expandNode(treeNode, false, false, true);
      };
      /**
       * 展开指定的节点，子节点递归展开
       * @param treeNode 指定展开的节点对象
       */
      var collapseNodeAll = function (treeNode) {
        return currentZtreeObj.expandNode(treeNode, false, true, true);
      };

      /**
       * 获取所有节点
       */
      var getAllNodes = function(){
        return  currentZtreeObj.transformToArray(currentZtreeObj.getNodes());
      };

      /**
       * 根据参数查找节点 （内容全部匹配）
       * @param key  查找数据对象JSON的key，不能为空
       * @param value   查找key 对应的值，不能为空
       * @param nodeObj   制定节点的查找范围,允许为空
       */
      var findNodesByParam = function(key,value,nodeObj){
        if(key == undefined || key == "" || key == null ){
          return [];
        }
        if(value == undefined || value == "" || value == null ){
          return [];
        }
        if(nodeObj == undefined || nodeObj == ""  ){
          nodeObj = null;
        }
        return currentZtreeObj.getNodesByParam(key, value, nodeObj);
      };

      /**
       * 根据tid 查找节点
       * @param tid   ztree 动态节点的唯一标志,是一个字符串
       * @returns {JSON}
       */
      var findNodeByTid = function(tid){
        if(tid == undefined || tid == "" || tid == null ){
          return null;
        }
        return currentZtreeObj.getNodeByTId(tid);
      };

      /**
       * 获取用户选中的节点
       * @returns {Array}
       */
      var getSelectedNodes = function () {
        return currentZtreeObj.getSelectedNodes();
      };

      /**
       * 定位某个节点，
       * @param treeNode  需要定位的节点
       * @param isExpand   是否需要展开节点
       * @param isExpandAllSubNode   是否需要展开所有的子节点
       */
      var locationNode = function (treeNode, isExpand , isExpandAllSubNode){
        //      expandNodeOnly(treeNode)
        expandNodeAll(treeNode)
      };

      return {
        // 展开所有节点
        "expandAll" : expandAll,
        "expandNodeOnly" : expandNodeOnly,
        "expandNodeAll" : expandNodeAll,
        "collapseAll" : collapseAll,
        "collapseNodeOnly" : collapseNodeOnly,
        "collapseNodeAll" : collapseNodeAll,
        "getAllNodes" : getAllNodes,
        "findNodesByParam" : findNodesByParam,
        "findNodeByTid" : findNodeByTid,
        "getSelectedNodes" : getSelectedNodes,
        "locationNode" : locationNode,
      }
    },

    /**
     * 获取ztree的ID
     * @returns {string}
     */
    getTreeId : function(){
      return "#"+treeId;
    },

    /**
     * 获取ztree的ID，不带jquery选择器
     * @returns {string}
     */
    getTreeIdStr : function(){
      return treeId;
    },

    /**
     * 对ztree 的数据做转换
     * 1、 根据用户自定义的字段，作为显示的内容
     */
    ztreeDataFormat : function(vueObj){
      var length = vueObj.ztreeData.length;
      for(var i = 0; i < length; i++){
        var tempObj = vueObj.ztreeData[i];
        tempObj["name"] = tempObj[vueObj.nodeHtmlKey];
      }
    },

  };


  export default {
    props: {
      // 用户传递过来的数据
      navData: {
        default: function(){
          return []
        }
      },
      // 是否是simpleData 格式的数据（即数组的形式，非JSON格式）
      isSimpleData: {
        type: Boolean,
        default: true
      },
      // 是否是 outlook 风格
      isOutlookStyle: {
        type: Boolean,
        default: true
      },
      // 指明数据节点的 id  key的名字，
      nodeIdKey: {
        type: String,
        default: "id"
      },
      // 指明数据节点的 pid  key的名字，
      nodePidKey: {
        type: String,
        default: "pid"
      },
      // 指明数据节点的 name  key的名字，
      nodeHtmlKey: {
        type: String,
        default: "nodeHtml"
      },
    },
    mounted: function(){
      new navTreeTools(this);
    },
    data: function () {
      return {
        treeId: treeId
      }
    },
    computed: {},
    methods: {
      // 缓存ztree的配置信息
      setZtreeSetting: function (ztreeSetting) {
        this.ztreeSetting = ztreeSetting;
      },
      reCreateTree: function(){
        var  that = this;
        window.setTimeout(function(){
          new navTreeTools(that);
        },200)
      }
    },
    // 监听传入数据的变化
    watch: {
// 用户传递过来的数据
      navData: function (newValue, oldValue) {
        this.navData = newValue;
        this.reCreateTree();
      },
      // 是否是simpleData 格式的数据（即数组的形式，非JSON格式）
      isSimpleData: function (newValue, oldValue) {
        this.reCreateTree();
      },
      // 是否是 outlook 风格
      isOutlookStyle: function (newValue, oldValue) {
        this.reCreateTree();
      },
      // 指明数据节点的 id  key的名字，
      nodeIdKey: function (newValue, oldValue) {
        this.reCreateTree();
      },
      // 指明数据节点的 pid  key的名字，
      nodePidKey: function (newValue, oldValue) {
        this.reCreateTree();
      },
      // 指明数据节点的 name  key的名字，
      nodeHtmlKey: function (newValue, oldValue) {
        this.reCreateTree();
      },
    },
  }
</script>


<style lang="scss">
    @import '../../style/styleKit.scss';
    /* 节点的高度 */
    $ztree-li-height: 36px;
    .zlst-frame-nav{
        .ztree {
            padding:5px 0;
            li {
                padding: 0;
                margin: 0;
                list-style: none;
                line-height:$ztree-li-height;
                text-align: left;
                white-space: nowrap;
                outline: 0;
                font-size: 14px!important;
                ul{
                    margin:0!important;
                    padding:0!important;
                }
                span.button{
                    background-image:url(../../../static/ztree/css/zTreeStyle/img/menu_tree.png)!important;
                }
                a:hover{
                    background:#f8f9fb url("../../../static/ztree/css/zTreeStyle/img/menu_tree_curSelectedNode.png") repeat-y;
                }
                a.curSelectedNode{
                    border:none;
                    background:#f8f9fb url("../../../static/ztree/css/zTreeStyle/img/menu_tree_curSelectedNode.png") repeat-y;
                    color:$color-font2;
                }
                a.level0{
                    color:$color-font2;
                }

                a{
                    width:100%;
                    height:$ztree-li-height;
                    color:#9a9ea0;
                    padding-left:20px;
                    .node_name{
                        /*font-weight: bold;*/
                        .iconfont{
                            color:$color-font5;
                        }
                    }
                    &:hover{
                        text-decoration: none;
                    }
                    span.button.noline_docu{
                        background-image:none!important;
                        cursor: default;
                    }
                    span {
                        line-height:$ztree-li-height;

                    }
                    /* 复选框隐藏状态 */


                    span.button.chk.radio_false_full{
                        background-position: -17px -36px
                    }
                    span.button.chk.radio_false_full_focus {
                        background-position: -17px -36px
                    }
                    span.button.chk.radio_true_full {
                        background-position: 0 -36px
                    }
                    span.button.chk.radio_true_full_focus {
                        background-position: 0 -36px
                    }
                    span.button.chk.radio_false_part {
                        background-position: -36px -35px
                    }
                    span.button.chk.radio_false_part_focus {
                        background-position: -36px -35px
                    }
                    span.button.chk.radio_true_disable {
                        background-position: -17px -36px
                    }
                    span.button.chk.checkbox_false_disable {
                        background-position: -54px 0;
                        opacity: 0.5;
                        cursor: not-allowed;
                    }
                    span.button.chk.checkbox_false_full {
                        background-position: -54px 0
                    }
                    span.button.chk.checkbox_false_full_focus {
                        background-position: -54px 0
                    }
                    span.button.chk.checkbox_true_full {
                        background-position: 0 0
                    }
                    span.button.chk.checkbox_true_full_focus {
                        background-position: 0 0
                    }
                    span.button.noline_open {
                        background-position: -18px -17px
                    }
                    span.button.noline_close {
                        background-position: 2px -17px
                    }
                    span.button.chk.checkbox_true_part {
                        background-position: -36px 0
                    }
                    span.button.chk.checkbox_true_part_focus {
                        background-position: -36px 0
                    }
                    span.button.chk.checkbox_false_part {
                        background-position: -36px 0
                    }
                    span.button.chk.checkbox_false_part_focus {
                        background-position: -36px 0
                    }
                    span.button.chk.checkbox_true_disable {
                        background-position: 0 0;
                        opacity: 0.8;
                        cursor: not-allowed;
                    }
                }
            }
        }
    }

</style>
